<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.8.0 -->
<title>0056: MVC IX – A Fancy ComboBox | gtkDcoding</title>
<meta name="generator" content="Jekyll v4.3.4" />
<meta property="og:title" content="0056: MVC IX – A Fancy ComboBox" />
<meta name="author" content="Ron Tarrant" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="GTK Tutorial - customize a ComboBox with images and text." />
<meta property="og:description" content="GTK Tutorial - customize a ComboBox with images and text." />
<link rel="canonical" href="http://localhost:4000/posts/0056-mvc-ix-a-combobox-with-flair.html" />
<meta property="og:url" content="http://localhost:4000/posts/0056-mvc-ix-a-combobox-with-flair.html" />
<meta property="og:site_name" content="gtkDcoding" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2019-07-26T00:00:00-04:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="0056: MVC IX – A Fancy ComboBox" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Ron Tarrant"},"dateModified":"2019-07-26T00:00:00-04:00","datePublished":"2019-07-26T00:00:00-04:00","description":"GTK Tutorial - customize a ComboBox with images and text.","headline":"0056: MVC IX – A Fancy ComboBox","mainEntityOfPage":{"@type":"WebPage","@id":"http://localhost:4000/posts/0056-mvc-ix-a-combobox-with-flair.html"},"url":"http://localhost:4000/posts/0056-mvc-ix-a-combobox-with-flair.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="stylesheet" href="../assets/main.css">
  <link rel="stylesheet" href="../css/style.css" /><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="gtkDcoding" /></head>
<body><header class="site-header" role="banner">

  <div class="wrapper"><a class="site-title" rel="author" href="../">gtkDcoding</a><nav class="site-nav">
        <input type="checkbox" id="nav-trigger" class="nav-trigger" />
        <label for="nav-trigger">
          <span class="menu-icon">
            <svg viewBox="0 0 18 15" width="18px" height="15px">
              <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
            </svg>
          </span>
        </label>

        <div class="trigger"><a class="page-link" href="../about.html">About</a><a class="page-link" href="../index-reverse.html">Posts in Date Order</a><a class="page-link" href="../topics.html">Blog Posts by Topic</a></div>
      </nav></div>
</header>
<main class="page-content" aria-label="Content">
      <div class="wrapper">
        <article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
	<header class="post-header">
		<link rel="stylesheet" href="../css/font_size.css" />
		<link rel="stylesheet" href="../css/figure.css" />
		<link rel="stylesheet" href="../css/topics/mvc.css" />  <!-- sub in the tag/topic -->
		<link rel="stylesheet" href="../css/modal.css" />
		<link rel="stylesheet" href="../css/post.css" />
		<link rel="stylesheet" href="../css/mascot_effects.css" />

		
		
		<p class="post-meta">
		<time class="dt-published" datetime="2019-07-26T00:00:00-04:00" itemprop="datePublished">Friday, July 26, 2019
		</time>• by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">Ron Tarrant</span></span></p>
	</header>

	<div class="post-content e-content" itemprop="articleBody">
		<div class="skew-line"></div>
		<h1 id="0056-mvc-ix--a-fancy-combobox">0056: MVC IX – A Fancy ComboBox</h1>

<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img0" src="../images/screenshots/017_mvc/mvc_13.png" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal0" class="modal">																	<!-- modal# -->
				<span class="close0">&times;</span>															<!-- close# -->
				<img class="modal-content" id="img00" />															<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal0");														// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img0");															// img#
			var modalImg = document.getElementById("img00");													// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close0")[0];											// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img1" src="../images/screenshots/017_mvc/mvc_13_term.png" alt="Current example terminal output" />		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal1" class="modal">																				<!-- modal# -->
				<span class="close1">&times;</span>																		<!-- close# -->
				<img class="modal-content" id="img11" />																		<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal1");																	// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img1");																		// img#
			var modalImg = document.getElementById("img11");																// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close1")[0];														// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																								<!-- ------------- filename (below) --------- -->
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/017_mvc/mvc_13_combobox_weather.d" target="_blank">here</a>.
	</div>
</div>

<p>And here’s a link to <a href="https://github.com/rontarrant/gtkd_demos/blob/master/downloads/weather_combobox.zip">the companion files</a>.</p>

<p>Everything presented today is something we’ve looked at before. What’s different is how it’s all put together to make the <em>Weather ComboBox</em> example. So, we’ll skim through to see those changes before checking out how this whole thing is put together.</p>

<p>First, there’s this import:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="n">singleton</span><span class="p">.</span><span class="n">S_DetectedOS</span><span class="p">;</span>
</code></pre></div></div>

<p>It’s there because we need to know which OS we’re working with, but we’ll talk more about that in a moment.</p>

<p>And then there’s…</p>

<h2 id="the-appbox">The AppBox</h2>

<p>This is where we instantiate:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">weatherListStore</code>, and</li>
  <li><code class="language-plaintext highlighter-rouge">weatherComboBox</code>.</li>
</ul>

<p>But, that’s nothing unusual, so moving right along…</p>

<h2 id="the-weatherliststore-class">The WeatherListStore Class</h2>

<p>Right at the top of the preamble (which could also be referred to as the instantiation section, the list of class-level properties) we’ve got:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">S_DetectedOS</span> <span class="n">s_detectedOS</span><span class="p">;</span>
</code></pre></div></div>

<p>Because fonts aren’t all the same on every OS, this declares a singleton we use to discover which operating system we’re running on. Once we know that, we can look for fonts that fit the design we have in mind.</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">string</span><span class="p">[]</span> <span class="n">_textItems</span> <span class="p">=</span> <span class="p">[</span><span class="s">"Sunny"</span><span class="p">,</span> <span class="s">"Partly Cloudy"</span><span class="p">,</span> <span class="s">"Cloudy"</span><span class="p">,</span> <span class="s">"Rainy"</span><span class="p">,</span> <span class="s">"Thunderstorm"</span><span class="p">,</span> <span class="s">"Snowy"</span><span class="p">];</span>
<span class="nb">string</span><span class="p">[]</span> <span class="n">_fontNames</span><span class="p">;</span>
<span class="kt">int</span><span class="p">[]</span> <span class="n">_fontSizes</span> <span class="p">=</span> <span class="p">[</span><span class="mi">12</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">17</span><span class="p">];</span>

<span class="kt">float</span><span class="p">[][]</span> <span class="n">_fgColors</span> <span class="p">=</span> <span class="p">[[</span><span class="mf">.0</span><span class="mi">27</span><span class="p">,</span> <span class="mf">.0</span><span class="mi">67</span><span class="p">,</span> <span class="mf">.855</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">.0</span><span class="mi">2</span><span class="p">,</span> <span class="mf">.0</span><span class="mi">43</span><span class="p">,</span> <span class="mf">.576</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">.0</span><span class="mi">12</span><span class="p">,</span> <span class="mf">.0</span><span class="mi">31</span><span class="p">,</span> <span class="mf">.404</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> 
								 <span class="p">[</span><span class="mf">.741</span><span class="p">,</span> <span class="mf">.757</span><span class="p">,</span> <span class="mf">.816</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">.894</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">.933</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">]];</span>
								 
<span class="kt">float</span><span class="p">[][]</span> <span class="n">_bgColors</span> <span class="p">=</span> <span class="p">[[</span><span class="mf">.592</span><span class="p">,</span> <span class="mf">.957</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">.522</span><span class="p">,</span> <span class="mf">.847</span><span class="p">,</span> <span class="mf">.882</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">.365</span><span class="p">,</span> <span class="mf">.596</span><span class="p">,</span> <span class="mf">.62</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> 
								 <span class="p">[</span><span class="mf">.259</span><span class="p">,</span> <span class="mf">.42</span><span class="p">,</span> <span class="mf">.435</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">.18</span><span class="p">,</span> <span class="mf">.29</span><span class="p">,</span> <span class="mf">.302</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">1.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">]];</span>

<span class="nb">string</span><span class="p">[]</span> <span class="n">_images</span> <span class="p">=</span> <span class="p">[</span><span class="s">"_images/sun_50x.png"</span><span class="p">,</span> <span class="s">"_images/partly_cloudy_50x.png"</span><span class="p">,</span> <span class="s">"_images/cloudy_50x.png"</span><span class="p">,</span>
							 <span class="s">"_images/rainy_50x.png"</span><span class="p">,</span> <span class="s">"_images/thunder_50x.png"</span><span class="p">,</span> <span class="s">"_images/snowy_50x.png"</span><span class="p">];</span>
</code></pre></div></div>

<p>After that comes:</p>

<ul>
  <li>a list of text arrays,</li>
  <li>font names and sizes,</li>
  <li>background and foreground colors—which can be set for each individual item in a <code class="language-plaintext highlighter-rouge">ComboBox</code>’s list—and</li>
  <li>finishing up with a list of image file names we’ll load in the constructor.</li>
</ul>

<p>Next are declarations for a <code class="language-plaintext highlighter-rouge">PgFontDescription</code> and a <code class="language-plaintext highlighter-rouge">TreeIter</code>, followed by an auto-numbered <code class="language-plaintext highlighter-rouge">Column</code> enum, all of which we used last time. Notice that the <code class="language-plaintext highlighter-rouge">enum</code> is in the <code class="language-plaintext highlighter-rouge">public</code> section of our class so it can be accessed directly from inside other classes. <em>(Note: <code class="language-plaintext highlighter-rouge">public</code> and <code class="language-plaintext highlighter-rouge">private</code> will only take on their true meanings if we move this class into its own module.)</em></p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">PgFontDescription</span> <span class="n">fontDesc</span><span class="p">;</span>
<span class="n">TreeIter</span> <span class="n">_treeIter</span><span class="p">;</span>
	
<span class="k">public</span><span class="p">:</span>
<span class="k">enum</span> <span class="n">Column</span>
<span class="p">{</span>
	<span class="n">TEXT</span> <span class="p">=</span> <span class="mi">0</span><span class="p">,</span>
	<span class="n">FONT</span><span class="p">,</span>
	<span class="n">COLOR_ON</span><span class="p">,</span>
	<span class="n">FG_COLOR</span><span class="p">,</span>
	<span class="n">BG_COLOR</span><span class="p">,</span>
	<span class="n">IMAGE</span>
	
<span class="p">}</span> <span class="c1">// enum Column</span>
</code></pre></div></div>

<h2 id="the-weatherliststore-constructor">The WeatherListStore Constructor</h2>

<p>There’s a lot going on here, so let’s break it down a bit…</p>

<h3 id="initialization">Initialization</h3>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">string</span> <span class="n">textItem</span><span class="p">,</span> <span class="n">fontName</span><span class="p">,</span> <span class="n">imageName</span><span class="p">;</span>
<span class="kt">float</span> <span class="n">fgRed</span><span class="p">,</span> <span class="n">bgRed</span><span class="p">,</span> <span class="n">fgGreen</span><span class="p">,</span> <span class="n">fgAlpha</span><span class="p">,</span> <span class="n">bgGreen</span><span class="p">,</span> <span class="n">fgBlue</span><span class="p">,</span> <span class="n">bgBlue</span><span class="p">,</span> <span class="n">bgAlpha</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">fontSize</span><span class="p">;</span>
		
<span class="k">super</span><span class="p">([</span><span class="n">GType</span><span class="p">.</span><span class="n">STRING</span><span class="p">,</span> <span class="n">PgFontDescription</span><span class="p">.</span><span class="n">getType</span><span class="p">(),</span> <span class="n">GType</span><span class="p">.</span><span class="n">INT</span><span class="p">,</span> <span class="n">RGBA</span><span class="p">.</span><span class="n">getType</span><span class="p">(),</span> <span class="n">RGBA</span><span class="p">.</span><span class="n">getType</span><span class="p">(),</span> <span class="n">Pixbuf</span><span class="p">.</span><span class="n">getType</span><span class="p">()]);</span>

<span class="n">assignFonts</span><span class="p">();</span>
</code></pre></div></div>

<p>Notice that the colors are broken down into red, green, and blue components and they’re all floating point. We’ll talk more about that in a moment.</p>

<p>And our array of <code class="language-plaintext highlighter-rouge">GType</code>s shows several examples of how to grab a <code class="language-plaintext highlighter-rouge">GType</code> from a <em>GTK</em> or <em>GDK</em> class using the <code class="language-plaintext highlighter-rouge">getType()</code> function.</p>

<p>Lastly, we make a call to the <code class="language-plaintext highlighter-rouge">assignFonts()</code> function which we’ll talk about later.</p>

<h3 id="building-the-store">Building the Store</h3>

<p>We build the store with this code where we grab a text description of the weather, a font name, and a size:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">foreach</span><span class="p">(</span><span class="kt">ulong</span> <span class="n">i</span><span class="p">;</span> <span class="mf">0.</span><span class="p">.</span><span class="n">_textItems</span><span class="p">.</span><span class="n">length</span><span class="p">)</span>
<span class="p">{</span>
	<span class="n">textItem</span> <span class="p">=</span> <span class="n">_textItems</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
	<span class="n">fontName</span> <span class="p">=</span> <span class="n">_fontNames</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
	<span class="n">fontSize</span> <span class="p">=</span> <span class="n">_fontSizes</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</code></pre></div></div>

<p>Then put together the R, G, B, and alpha components of the colors:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fgRed</span> <span class="p">=</span> <span class="n">_fgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
<span class="n">fgGreen</span> <span class="p">=</span> <span class="n">_fgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
<span class="n">fgBlue</span> <span class="p">=</span> <span class="n">_fgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">2</span><span class="p">];</span>
<span class="n">fgAlpha</span> <span class="p">=</span> <span class="n">_fgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span>
		
<span class="n">bgRed</span> <span class="p">=</span> <span class="n">_bgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
<span class="n">bgGreen</span> <span class="p">=</span> <span class="n">_bgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
<span class="n">bgBlue</span> <span class="p">=</span> <span class="n">_bgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">2</span><span class="p">];</span>
<span class="n">bgAlpha</span> <span class="p">=</span> <span class="n">_bgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span>
</code></pre></div></div>

<p>Look back at the instantiation section of the <code class="language-plaintext highlighter-rouge">WeatherListStore</code> and note that the numbers for the colors range between 0.0 and 1.0. If you work out your color palette in <em>Photoshop</em> or using online web-related resources, you’ll likely end up with R, G, and B values ranging from 0 to 255, but to convert them is easy and could even be done right here in the constructor like this:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fgRed</span> <span class="p">=</span> <span class="n">_fgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="p">/</span> <span class="mi">255</span><span class="p">;</span>
<span class="n">bgGreen</span> <span class="p">=</span> <span class="n">_bgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="p">/</span> <span class="mi">255</span><span class="p">;</span>
<span class="n">bgBlue</span> <span class="p">=</span> <span class="n">_bgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="p">/</span> <span class="mi">255</span><span class="p">;</span>
<span class="n">bgAlpha</span> <span class="p">=</span> <span class="n">_bgColors</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">3</span><span class="p">];</span>
</code></pre></div></div>

<p>But I opted to do the conversions off-screen, so to speak. Still, do the conversion for each component and you’re done.</p>

<p><em>Note: The alpha value is between 0.0 and 1.0, even for</em> CSS/HTML <em>so no conversion needed.</em></p>

<p><em>Note 2: In</em> Photoshop, <em>if you switch to 32-bit color values</em> (Image <em>menu &gt;</em> Mode <em>&gt;</em> 32-bits/Channel) <em>component values are between 0.0 and 1.0, so you won’t have to convert.</em></p>

<p>Next, we grab an image name:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">imageName</span> <span class="p">=</span> <span class="n">_images</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</code></pre></div></div>

<p>Instantiate the <code class="language-plaintext highlighter-rouge">TreeIter</code> and <code class="language-plaintext highlighter-rouge">PgFontDescription</code> objects:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_treeIter</span> <span class="p">=</span> <span class="n">createIter</span><span class="p">();</span>
<span class="n">fontDesc</span> <span class="p">=</span> <span class="k">new</span> <span class="n">PgFontDescription</span><span class="p">(</span><span class="n">fontName</span><span class="p">,</span> <span class="n">fontSize</span><span class="p">);</span>
</code></pre></div></div>

<p>And set all the values. Notice that we’re dealing with six columns here, most of which will be used for setting attributes when we get to building the <code class="language-plaintext highlighter-rouge">ComboBox</code>.</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	<span class="n">setValue</span><span class="p">(</span><span class="n">_treeIter</span><span class="p">,</span> <span class="n">Column</span><span class="p">.</span><span class="n">TEXT</span><span class="p">,</span> <span class="n">textItem</span><span class="p">);</span>
	<span class="n">setValue</span><span class="p">(</span><span class="n">_treeIter</span><span class="p">,</span> <span class="n">Column</span><span class="p">.</span><span class="n">FONT</span><span class="p">,</span> <span class="n">fontDesc</span><span class="p">);</span>
	<span class="n">setValue</span><span class="p">(</span><span class="n">_treeIter</span><span class="p">,</span> <span class="n">Column</span><span class="p">.</span><span class="n">COLOR_ON</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
	<span class="n">setValue</span><span class="p">(</span><span class="n">_treeIter</span><span class="p">,</span> <span class="n">Column</span><span class="p">.</span><span class="n">FG_COLOR</span><span class="p">,</span> <span class="k">new</span> <span class="n">RGBA</span><span class="p">(</span><span class="n">fgRed</span><span class="p">,</span> <span class="n">fgGreen</span><span class="p">,</span> <span class="n">fgBlue</span><span class="p">,</span> <span class="n">fgAlpha</span><span class="p">));</span>
	<span class="n">setValue</span><span class="p">(</span><span class="n">_treeIter</span><span class="p">,</span> <span class="n">Column</span><span class="p">.</span><span class="n">BG_COLOR</span><span class="p">,</span> <span class="k">new</span> <span class="n">RGBA</span><span class="p">(</span><span class="n">bgRed</span><span class="p">,</span> <span class="n">bgGreen</span><span class="p">,</span> <span class="n">bgBlue</span><span class="p">,</span> <span class="n">bgAlpha</span><span class="p">));</span>
	<span class="n">setValue</span><span class="p">(</span><span class="n">_treeIter</span><span class="p">,</span> <span class="n">Column</span><span class="p">.</span><span class="n">IMAGE</span><span class="p">,</span> <span class="k">new</span> <span class="n">Pixbuf</span><span class="p">(</span><span class="n">imageName</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="assigning-fonts">Assigning Fonts</h3>

<p>This function is where we find out which OS we’re running on and make sure the fonts are ones we’re likely to find on that platform. Here’s the code:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">assignFonts</span><span class="p">()</span>
<span class="p">{</span>
	<span class="n">s_detectedOS</span> <span class="p">=</span> <span class="n">s_detectedOS</span><span class="p">.</span><span class="n">get</span><span class="p">();</span>
		
	<span class="k">switch</span><span class="p">(</span><span class="n">s_detectedOS</span><span class="p">.</span><span class="n">getOS</span><span class="p">())</span>
	<span class="p">{</span>
		<span class="k">case</span> <span class="s">"Windows"</span><span class="p">:</span>
			<span class="n">writeln</span><span class="p">(</span><span class="s">"Windows found"</span><span class="p">);</span>
			<span class="n">_fontNames</span> <span class="p">=</span> <span class="p">[</span><span class="s">"Times New Roman"</span><span class="p">,</span> <span class="s">"Arial"</span><span class="p">,</span> <span class="s">"Georgia"</span><span class="p">,</span> <span class="s">"Verdana"</span><span class="p">,</span> <span class="s">"Comic Sans MS"</span><span class="p">,</span> <span class="s">"Courier New"</span><span class="p">];</span>
		<span class="k">break</span><span class="p">;</span>
			
		<span class="k">case</span> <span class="s">"OSX"</span><span class="p">:</span>
			<span class="n">_fontNames</span> <span class="p">=</span> <span class="p">[</span><span class="s">"Times New Roman"</span><span class="p">,</span> <span class="s">"Arial"</span><span class="p">,</span> <span class="s">"Georgia"</span><span class="p">,</span> <span class="s">"Verdana"</span><span class="p">,</span> <span class="s">"Comic Sans MS"</span><span class="p">,</span> <span class="s">"Courier New"</span><span class="p">];</span>
		<span class="k">break</span><span class="p">;</span>				
		
		<span class="k">case</span> <span class="s">"Posix"</span><span class="p">:</span>
			<span class="n">writeln</span><span class="p">(</span><span class="s">"Linux found"</span><span class="p">);</span>
			<span class="n">_fontNames</span> <span class="p">=</span> <span class="p">[</span><span class="s">"FreeSerif"</span><span class="p">,</span> <span class="s">"Garuda"</span><span class="p">,</span> <span class="s">"Century Schoolbook L"</span><span class="p">,</span> <span class="s">"Kalimati"</span><span class="p">,</span> <span class="s">"Purisa"</span><span class="p">,</span> <span class="s">"FreeMono"</span><span class="p">];</span>
		<span class="k">break</span><span class="p">;</span>

		<span class="k">default</span><span class="p">:</span>
			<span class="n">writeln</span><span class="p">(</span><span class="s">"No known OS found"</span><span class="p">);</span>
			<span class="n">_fontNames</span> <span class="p">=</span> <span class="p">[</span><span class="s">"Times New Roman"</span><span class="p">,</span> <span class="s">"Arial"</span><span class="p">,</span> <span class="s">"Georgia"</span><span class="p">,</span> <span class="s">"Verdana"</span><span class="p">,</span> <span class="s">"Comic Sans MS"</span><span class="p">,</span> <span class="s">"Courier New"</span><span class="p">];</span>
		<span class="k">break</span><span class="p">;</span>
	<span class="p">}</span> <span class="c1">// switch</span>
	
<span class="p">}</span> <span class="c1">// assignFonts()</span>
</code></pre></div></div>

<p>We start by instantiating a singleton for the detected OS, then use a switch statement to pick fonts based on which OS we find.</p>

<p>Now let’s get to…</p>

<h2 id="the-weathercombobox-class">The WeatherComboBox Class</h2>

<p>This is where everything comes together. We start off by declaring all the stuff we need:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="n">WeatherComboBox</span> <span class="p">:</span> <span class="n">ComboBox</span>
<span class="p">{</span>
	<span class="k">private</span><span class="p">:</span>
	<span class="kt">bool</span> <span class="n">entryOn</span> <span class="p">=</span> <span class="kc">false</span><span class="p">;</span>
	<span class="n">WeatherListStore</span> <span class="n">_weatherListStore</span><span class="p">;</span>
	<span class="n">CellRendererText</span> <span class="n">cellRendererText</span><span class="p">;</span>
	<span class="n">CellRendererPixbuf</span> <span class="n">cellRendererPixbuf</span><span class="p">;</span>
	<span class="kt">int</span> <span class="n">activeItem</span> <span class="p">=</span> <span class="mi">0</span><span class="p">;</span>
</code></pre></div></div>

<p>Note we’ve got the <code class="language-plaintext highlighter-rouge">Entry</code> flag turned off and the active item will be the first one in the <code class="language-plaintext highlighter-rouge">ListStore</code>.</p>

<p>And then the constructor:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span><span class="p">:</span>
<span class="k">this</span><span class="p">(</span><span class="n">WeatherListStore</span> <span class="n">weatherListStore</span><span class="p">)</span>
<span class="p">{</span>
	<span class="k">super</span><span class="p">(</span><span class="n">entryOn</span><span class="p">);</span>
</code></pre></div></div>

<p>where we set up and bring in the store:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">_weatherListStore</span> <span class="p">=</span> <span class="n">weatherListStore</span><span class="p">;</span>
<span class="n">setModel</span><span class="p">(</span><span class="n">_weatherListStore</span><span class="p">);</span>
<span class="n">setActive</span><span class="p">(</span><span class="n">activeItem</span><span class="p">);</span>
</code></pre></div></div>

<p>then hook up the callback signal:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">addOnChanged</span><span class="p">(&amp;</span><span class="n">doSomething</span><span class="p">);</span>
</code></pre></div></div>

<p>set up the <code class="language-plaintext highlighter-rouge">ComboBox</code>’s column to render text:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cellRendererText</span> <span class="p">=</span> <span class="k">new</span> <span class="n">CellRendererText</span><span class="p">();</span>
<span class="n">packStart</span><span class="p">(</span><span class="n">cellRendererText</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
<span class="n">addAttribute</span><span class="p">(</span><span class="n">cellRendererText</span><span class="p">,</span> <span class="s">"text"</span><span class="p">,</span> <span class="n">_weatherListStore</span><span class="p">.</span><span class="n">Column</span><span class="p">.</span><span class="n">TEXT</span><span class="p">);</span>
</code></pre></div></div>

<p>and grab attributes from the <code class="language-plaintext highlighter-rouge">ListStore</code>’s extra columns which are used to set the font, the text color, and background color:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">addAttribute</span><span class="p">(</span><span class="n">cellRendererText</span><span class="p">,</span> <span class="s">"font-desc"</span><span class="p">,</span> <span class="n">_weatherListStore</span><span class="p">.</span><span class="n">Column</span><span class="p">.</span><span class="n">FONT</span><span class="p">);</span>
<span class="n">addAttribute</span><span class="p">(</span><span class="n">cellRendererText</span><span class="p">,</span> <span class="s">"foreground-rgba"</span><span class="p">,</span> <span class="n">_weatherListStore</span><span class="p">.</span><span class="n">Column</span><span class="p">.</span><span class="n">FG_COLOR</span><span class="p">);</span>
<span class="n">addAttribute</span><span class="p">(</span><span class="n">cellRendererText</span><span class="p">,</span> <span class="s">"foreground-set"</span><span class="p">,</span> <span class="n">_weatherListStore</span><span class="p">.</span><span class="n">Column</span><span class="p">.</span><span class="n">COLOR_ON</span><span class="p">);</span>
<span class="n">addAttribute</span><span class="p">(</span><span class="n">cellRendererText</span><span class="p">,</span> <span class="s">"background-rgba"</span><span class="p">,</span> <span class="n">_weatherListStore</span><span class="p">.</span><span class="n">Column</span><span class="p">.</span><span class="n">BG_COLOR</span><span class="p">);</span>
<span class="n">addAttribute</span><span class="p">(</span><span class="n">cellRendererText</span><span class="p">,</span> <span class="s">"background-set"</span><span class="p">,</span> <span class="n">_weatherListStore</span><span class="p">.</span><span class="n">Column</span><span class="p">.</span><span class="n">COLOR_ON</span><span class="p">);</span>		
</code></pre></div></div>

<p>And we finish off by stuffing in a second <code class="language-plaintext highlighter-rouge">CellRenderer</code> for the images:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	<span class="n">cellRendererPixbuf</span> <span class="p">=</span> <span class="k">new</span> <span class="n">CellRendererPixbuf</span><span class="p">();</span>
	<span class="n">packStart</span><span class="p">(</span><span class="n">cellRendererPixbuf</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
	<span class="n">addAttribute</span><span class="p">(</span><span class="n">cellRendererPixbuf</span><span class="p">,</span> <span class="s">"pixbuf"</span><span class="p">,</span> <span class="n">_weatherListStore</span><span class="p">.</span><span class="n">Column</span><span class="p">.</span><span class="n">IMAGE</span><span class="p">);</span>
	
<span class="p">}</span> <span class="c1">// this()</span>
</code></pre></div></div>

<p>And just for completeness sake, here’s the OS detection module which you’ll find in the companion zip file (We linked to it at the top, but <a href="https://github.com/rontarrant/gtkd_demos/blob/master/downloads/weather_combobox.zip">here it is again</a>). Because we’ve seen these a couple of times already, I won’t go into detail, but it’s patterned after the same <a href="https://wiki.dlang.org/Low-Lock_Singleton_Pattern">thread-safe singleton found here</a>. And here it is, the <code class="language-plaintext highlighter-rouge">S_DetectedOS.d</code> module:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">module</span> <span class="n">DetectedOS</span><span class="p">;</span>

<span class="k">import</span> <span class="n">std</span><span class="p">.</span><span class="n">stdio</span><span class="p">;</span>

<span class="k">class</span> <span class="n">S_DetectedOS</span>
<span class="p">{</span>
	<span class="k">private</span><span class="p">:</span>
	<span class="nb">string</span> <span class="n">_os_type</span><span class="p">;</span>
	<span class="k">static</span> <span class="kt">bool</span> <span class="n">instantiated_</span><span class="p">;</span>
	<span class="k">__gshared</span> <span class="n">S_DetectedOS</span> <span class="n">instance_</span><span class="p">;</span>

	<span class="k">this</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="k">version</span><span class="p">(</span><span class="n">Windows</span><span class="p">)</span>
		<span class="p">{</span>
			<span class="n">_os_type</span> <span class="p">=</span> <span class="s">"Windows"</span><span class="p">;</span>
		<span class="p">}</span>
		<span class="k">else</span> <span class="k">version</span><span class="p">(</span><span class="n">OSX</span><span class="p">)</span>
		<span class="p">{</span>
			<span class="n">_os_type</span> <span class="p">=</span> <span class="s">"OSX"</span><span class="p">;</span>
		<span class="p">}</span>
		<span class="k">else</span> <span class="k">version</span><span class="p">(</span><span class="n">Posix</span><span class="p">)</span>
		<span class="p">{</span>
			<span class="n">_os_type</span> <span class="p">=</span> <span class="s">"Posix"</span><span class="p">;</span>
		<span class="p">}</span>

	<span class="p">}</span> <span class="c1">// this()</span>


	<span class="k">public</span><span class="p">:</span>
	<span class="k">static</span> <span class="n">S_DetectedOS</span> <span class="n">get</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="k">if</span><span class="p">(!</span><span class="n">instantiated_</span><span class="p">)</span>
		<span class="p">{</span>
			<span class="k">synchronized</span><span class="p">(</span><span class="n">S_DetectedOS</span><span class="p">.</span><span class="n">classinfo</span><span class="p">)</span>
			<span class="p">{</span>
				<span class="k">if</span><span class="p">(!</span><span class="n">instance_</span><span class="p">)</span>
				<span class="p">{</span>
					<span class="n">instance_</span> <span class="p">=</span> <span class="k">new</span> <span class="n">S_DetectedOS</span><span class="p">();</span>
				<span class="p">}</span>

				<span class="n">instantiated_</span> <span class="p">=</span> <span class="kc">true</span><span class="p">;</span>
			<span class="p">}</span>
		<span class="p">}</span>
		
		<span class="k">return</span><span class="p">(</span><span class="n">instance_</span><span class="p">);</span>
		
	<span class="p">}</span> <span class="c1">// DetectedOS()</span>
	
	
	<span class="nb">string</span> <span class="n">getOS</span><span class="p">()</span>
	<span class="p">{</span>
		<span class="n">writeln</span><span class="p">(</span><span class="s">"returning: "</span><span class="p">,</span> <span class="n">_os_type</span><span class="p">);</span>
		<span class="k">return</span><span class="p">(</span><span class="n">_os_type</span><span class="p">);</span>
		
	<span class="p">}</span> <span class="c1">// getOS()</span>

<span class="p">}</span> <span class="c1">// class S_DetectedOS</span>
</code></pre></div></div>

<p>And that’s it.</p>

<h2 id="conclusion">Conclusion</h2>

<p>It came as a surprise to me when I discovered all this. Who’d’a thunk you could get so fancy with a <code class="language-plaintext highlighter-rouge">ComboBox</code>.</p>

<p>Until next time, happy computing.</p>

<div class="blog-nav">
	<div style="float: left;">
		<a href="./0055-mvc-viii-dynamically-loading-a-treeview.html">Previous: TreeView - Dynamic Population</a>
	</div>
	<div style="float: right;">
		<a href="./0057-cairo-i-the-basics.html">Next: Introduction to Cairo Drawing</a>
	</div>
</div>
<p>
	<h3></h3>
<div class="inpage-frame">
	<a href="https://github.com/sponsors/rontarrant">
		<BR>
		<BR>
		<B>Is this article useful? Educational? Entertaining, perhaps?</B>
		<BR>
		<figure class="left">
			<img src="../images/favorite_32.png" alt="Sponsorship heart" style="width: 32px; height: 32px;">
		</figure>
		You're free to accept or decline this invitation to become our newest sponsor.
	</a>
</div>
	<h4 class="comment-blurb"><B>Comments? Questions? Observations?</B></h4>
	<p>
		Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
	</p>
	<script src="https://utteranc.es/client.js"
		repo="rontarrant"
		issue-term="pathname"
		theme="github-light"
		crossorigin="anonymous"
		async>
	</script>
	<ul>
		<li> come on over to the <a href="https://forum.dlang.org/">D Language Forum</a> and look for one of the <i>gtkDcoding</i> announcement posts, </li>
		<li> drop by <a href="https://forum.gtkd.org/">the <i>GtkD Forum</i></a>,</li>
		<li> follow the link below to email me, or</li>
		<li> go to the	<a href="https://www.facebook.com">gtkDcoding Facebook page.</a></li>
	</ul>
</p>
<p> You can also subscribe <a href="/feed.xml">via RSS</a> so you won't miss anything. Thank you very much for dropping by.</p>
<p>&copy; Copyright 2025 Ron Tarrant </p>
</div>

	<a class="u-url" href="./0056-mvc-ix-a-combobox-with-flair.html" hidden></a>
</article>

      </div>
    </main><footer class="site-footer h-card">
  <data class="u-url" href="/"></data>

  <div class="wrapper">

    <h2 class="footer-heading">gtkDcoding</h2>

    <div class="footer-col-wrapper">
      <div class="footer-col footer-col-1">
        <ul class="contact-list">
          <li class="p-name">Ron Tarrant</li><li><a class="u-email" href="mailto:gtkDcoding@gmail.com">gtkDcoding@gmail.com</a></li></ul>
      </div>

      <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/rontarrant"><svg class="svg-icon"><use xlink:href="../assets/minima-social-icons.svg#github"></use></svg> <span class="username">rontarrant</span></a></li></ul>
</div>

      <div class="footer-col footer-col-3">
        <p>Simple examples of how to use GtkD to build GUI applications.</p>
      </div>
    </div>

  </div>

</footer>
</body>

</html>
